﻿#include <iostream> 
#include <memory>
#include <future>
#include <vector>

#include <algorithm>
#include <string>

using namespace std;

auto PointerSizeTest()->void;
class A : public std::enable_shared_from_this<A>
{
public:
	explicit A(const std::string& data) {
		m_data1 = std::make_unique<std::string>(data);
		m_data2 = std::make_shared<std::string>(data);
	}

	explicit A(const char* data, int datalen) {
		m_data1 = std::make_unique<std::string>(data, datalen);
		m_data2 = std::make_shared<std::string>(data, datalen);
	}

	std::unique_ptr<std::string>& getData1() {
		return m_data1;
	}

	std::shared_ptr<std::string> getData2() {
		return m_data2;
	}
	void TestSharedFromThis() {
		std::thread([](const std::shared_ptr<A>& spA)->void {
			std::this_thread::sleep_for(std::chrono::seconds(10));
			spA->getData2()->resize(10, '\0');
			std::cout << "test3 in thread.\n";
			}, shared_from_this()).detach();
	}
protected:

private:
	std::unique_ptr<std::string> m_data1{ nullptr };
	std::shared_ptr<std::string> m_data2{ nullptr };
};

auto create_unique_ptr(const std::string& ss)->std::unique_ptr<A>
{
	return std::unique_ptr<A>(new A(ss));
}

int main(int argc, char* argv[])
{ 
	std::vector<std::unique_ptr<A>> vecs;
	for (auto i = 0; i < 10; ++i)
	{
		auto  ptr = create_unique_ptr(std::to_string(i));
		vecs.emplace_back(std::move(ptr));
	}

	for (auto &it : vecs)
	{
		std::cout << *(it->getData1()) << std::endl;
	}
	PointerSizeTest();

// std::string s1{ "1234567890" };

// {
// 	auto a{ std::make_shared<A>(s1) };
// 	auto& data1 = a->getData1();
// 	auto&& data2 = a->getData2();
// 	std::weak_ptr<std::string> wp_data2 = data2;
// 	a->TestSharedFromThis();
// 	std::cout << "test1." << std::endl;
// }
// std::cout << "test2." << std::endl;

// getchar();
	return 0;
}

auto PointerSizeTest()->void
{
	std::cout << "unique_ptr: size = " << sizeof(std::unique_ptr<int>) << std::endl;
	std::cout << "shared_ptr: size =" << sizeof(std::shared_ptr<int>) << std::endl;
	std::cout << "weak_ptr: size =" << sizeof(std::weak_ptr<int>) << std::endl;
}
